// 7.3 类的其他特性
// 这些特性包括：类型成员、类的成员的类内初始值、可变数据成员、内联成员函数、从成员函数返回＊this
// 关于如何定义并使用类类型及友元类的更多知识。

// 7.3.4 友元再探
/**
 * 类还可以把其他的类定义成友元，也可以把其他类（之前已定义过的）的成员函数定义成友元。
 * 此外，友元函数能定义在类的内部，这样的函数是隐式内联的。
 * 
 * 必须要注意的一点是，友元关系不存在传递性。
 * 也就是说，如果Window_mgr有它自己的友元，则这些友元并不能理所当然地具有访问Screen的特权。
 * 
 * 每个类负责控制自己的友元类或友元函数。
 * 可以单独令Window_mgr的成员函数作为Screen的友元。
 * 
 * 友元函数可以定义在类的内部.
 * 
 * 当一个名字第一次出现在一个友元声明中时，我们隐式地假定该名字在当前作用域中是可见的。
 * 然而，友元本身不一定真的声明在当前作用域中（参见7.2.1节，第241页）。
 */

#include <iostream>
#include <vector>
#include "Sales_data.h"
using std::cerr, std::clog;
using std::cin, std::cout, std::endl;

// Screen类的声明
class Screen; // 这种声明有时被称作前向声明（forward declaration）

// 一旦一个类的名字出现后，它就被认为是声明过了（但尚未定义），因此类允许包含指向它自身类型的引用或指针
class Link_screen{
    //Screen window; // 错误，此时只被声明未被定义的Screen是不完全类型
    Link_screen *next;
    Link_screen *prev;
};

// 类之间的友元关系
// 举个友元类的例子，我们的Window_mgr类（参见7.3.1节，第245页）的某些成员可能需要访问它管理的Screen类的内部数据
class Screen{
    friend class Window_mgr; // Window_mgr的成员可以访问Screen类的私有部分
    // 令成员函数作为友元
    //friend void Window_mgr::clear(ScreenIndex);
};

// 友元声明和作用域
// 即使我们仅仅是用声明友元的类的成员调用该友元函数，它也必须是被声明过的
struct X {
    friend void f() { } // 友元函数可以定义在类的内部
    X() { f(); } // 错误，f还没有被声明
    void g();
    void h();
};
void X::g() { return f(); } // 错误，f还没有被声明
void f(); // 声明定义在X中的f
void X::h() { return f(); } // 正确，现在f的声明在作用域中出现了


int main()
{
    return 0;
}